classdef TestDotsPhenomenon < dotsTestCase
    
    properties
        nDims;
        dimensions;
        dimPartitions;
        partOperators;
        comositeHows;
    end
    
    methods
        function self = TestDotsPhenomenon(name)
            self = self@dotsTestCase(name);
        end
        
        
        function setUp(self)
            self.setUp@dotsTestCase;
            self.partOperators = {'<', '>', '<=', '>=', '=='};
            self.dimensions = dotsFiniteDimension.empty;
            self.nDims = 5;
            self.prepareDims;
        end
        
        function tearDown(self)
            self.tearDown@dotsTestCase;
        end
        
        function prepareDims(self)
            self.dimensions = dotsFiniteDimension.empty;
            for ii = 1:self.nDims
                self.dimensions(ii) = ...
                    dotsFiniteDimension.newLinear(1, ii, ii);
                self.dimensions(ii).name = sprintf('dim-%d', ii);
                self.dimPartitions(ii) = ceil(ii/2);
            end
        end
        
        function testTemplate(self)
            temp = dotsPhenomenon.template('temp', self.dimensions);
            sz = size(temp.space);
            assertEqual(sz(1:self.nDims), [self.dimensions.size], ...
                'phenomenon space size should match sizes of given dimensions')
        end
        
        function testPartitions(self)
            temp = dotsPhenomenon.template('temp', self.dimensions);
            
            for ii = 1:self.nDims
                for jj = 1:length(self.partOperators)
                    part = dotsPhenomenon.partition(temp, ...
                        self.dimensions(ii).name, ...
                        self.dimPartitions(ii), ...
                        self.partOperators{jj});
                    self.verifyPartitionSize(part);
                end
            end
        end
        
        function verifyPartitionSize(self, phenom)
            partDim = phenom.partitionDimension;
            sizes = [phenom.dimensions.size];
            sizes(partDim) = length(phenom.dimensions(partDim).indexes);
            sizeByIndexes = prod(sizes);
            
            sizeBySum = dotsPhenomenon.getSize(phenom);
            assertEqual(sizeByIndexes, sizeBySum, ...
                sprintf('partition on dim %d of %d has wrong size', ...
                partDim, length(sizes)));
        end
        
        function testComposites(self)
            temp = dotsPhenomenon.template('temp', self.dimensions);
            
            for ii = 1:self.nDims
                for jj = 1:length(self.partOperators)
                    part(jj) = dotsPhenomenon.partition(temp, ...
                        self.dimensions(ii).name, ...
                        self.dimPartitions(ii), ...
                        self.partOperators{jj});
                end
                
                inParts = dotsPhenomenon.composite(part, 'intersection');
                inSize = dotsPhenomenon.getSize(inParts);
                assertEqual(inSize, 0, ...
                    'partitions should have empty intersection');
                
                unParts = dotsPhenomenon.composite(part, 'union');
                [unSize, spaceSize] = dotsPhenomenon.getSize(unParts);
                assertEqual(unSize, spaceSize, ...
                    'partitions should have total union');
            end
        end
        
        function testComplements(self)
            temp = dotsPhenomenon.template('temp', self.dimensions);
            
            for ii = 1:self.nDims
                for jj = 1:length(self.partOperators)
                    part = dotsPhenomenon.partition(temp, ...
                        self.dimensions(ii).name, ...
                        self.dimPartitions(ii), ...
                        self.partOperators{jj});
                    
                    comp = dotsPhenomenon.complement(part);
                    self.verifyComplements(part, comp);
                end
            end
        end
        
        function verifyComplements(self, phenom, comp)
            [pPart, pSpace] = dotsPhenomenon.getSize(phenom);
            [cPart, cSpace] = dotsPhenomenon.getSize(comp);
            
            assertEqual(pSpace, cSpace, ...
                'phenomenon and complement must represent same space')
            
            assertEqual(pPart+cPart, pSpace, ...
                'phenomenon and complement partitions must sum to total space size')
        end
    end
end